package net.aetherial.context.grounding.annotators;

import java.util.*;

import net.aetherial.context.grounding.estimators.*;


import edu.smu.tspell.wordnet.*;

/**
 * Annotates a conversational unit by replacing instances of word forms with base forms. Not used in the current version.
 */

public class WordNetAnnotator extends Annotator
{
	private WordNetDatabase database;
	private PunctuationStrippingAnnotator punctStripper;

	private static HashSet<String> ignoreWords;

	static 
	{
		String[] list = {

				// Pronouns

				"all", "another", "any", "anybody", "anyone", "anything", "both", 
				"each", "each other", "either", "everybody", "everyone", "everything", "few", "he", "her", "hers", 
				"herself", "him", "himself", "his", "i", "it", "its", "itself", "little", "many", "me", "mine", 
				"more", "most", "much", "myself", "neither", "no one", "nobody", "none", "nothing", "one", 
				"one another", "other", "others", "ours", "ourselves", "several", "she", "some", "somebody", 
				"someone", "something", "that", "theirs", "them", "themselves", "these", "they", "this", "those", 
				"us", "we", "what", "whatever", "which", "whichever", "who", "whoever", "whom", "whomever", 
				"whose", "you", "yours", "yourself", "yourselves",

				// Articles
				"a", "an", "the"};

		ignoreWords = new HashSet<String> ();

		for (String word: list)
			ignoreWords.add (word);
	}

	/**
	 * Constructor. 
	 */
	
	public WordNetAnnotator ()
	{
		super ();

		System.setProperty ("wordnet.database.dir", "/Users/cjkarr/Desktop/dict");

		database = WordNetDatabase.getFileInstance ();
		punctStripper = new PunctuationStrippingAnnotator ();
	}

	/**
	 * Returns "WordNet Layer"
	 * @see net.aetherial.context.grounding.annotators.Annotator#getLayerName()
	 */
	
	public String getLayerName ()
	{
		return "WordNet Layer";
	}

	/**
	 * Utility function for returning the part of speech of for a <code>SynsetType</code>.
	 * 
	 * @param type		Type data structure
	 * @return			Part of speech
	 */
	
	public static String getTypeName (SynsetType type)
	{
		if (type == SynsetType.ADJECTIVE)
			return "adj.";
		else if (type == SynsetType.ADJECTIVE_SATELLITE)
			return "adj. sat.";
		else if (type == SynsetType.ADVERB )
			return "adv.";
		else if (type == SynsetType.NOUN)
			return "n.";
		else if (type == SynsetType.VERB)
			return "v.";
		else
			return "o.";
	}

	/**
	 * @see net.aetherial.context.grounding.annotators.Annotator#annotate(java.lang.String, java.lang.String, double)
	 */
	
	public Map<String, Object> annotate (String sender, String contribution, double score)
	{
		Map<String, Object> layer = super.annotate (sender, contribution, score);
		
		layer.put (Estimator.CONTRIBUTION_KEY, this.annotate (contribution));
		
		return layer;
	}

	/**
	 * Returns the annotated version of the conversational unit.
	 * 
	 * @param contribution	Original conversational unit.
	 * @return				Annotated version.
	 */
	
	public String annotate (String contribution) 
	{
		contribution = punctStripper.annotate (contribution);

		String[] words = contribution.split (" ");

		if (words.length > 0)
		{
			ArrayList<String> output = new ArrayList<String> ();

			for (String word: words)
			{

				if (ignoreWords.contains (word))
				{
					output.add (word);
				}
				else
				{	
					Synset[] synsets = database.getSynsets (word);

					if (synsets.length > 0)
					{
						HashMap<String, Integer> counts = new HashMap<String, Integer> ();
						for (Synset synset: synsets)
						{
							String type = synset.getWordForms ()[0]; // getTypeName (synset.getType ());

							Integer i = counts.get(type);

							if (i == null)
								i = new Integer (0);

							i = i + 1;

							counts.put (type, i);
						}

						String maxType = null;
						int maxCount = 0;

						for (String type: counts.keySet ())
						{
							if (counts.get (type) > maxCount)
							{
								maxCount = counts.get (type);
								maxType = type;
							}
						}

						output.add (maxType);
					}
					else
						output.add (word);
				}
			}

			StringBuffer sb = new StringBuffer ();

			for (String word: output)
			{
				sb.append (word);
				sb.append (" ");
			}

			return (sb.toString ());
		}

		return null;
	}
}